
class Series {
    private _data: any[];
    private _index: any[]=[];
    private columns: any[]=[];
    private dtypes: any[]=[];
    // { columns = [], dtypes = [], index = [] } = {}
    constructor(data: any[], options:{ columns?:any[], dtypes?:any[], index?:any[]}={}) {
        this._data = data;
        if(options.index){
            this._index = options.index;
        }
        if(options.columns){
            this.columns = options.columns;
        }
        if(options.dtypes){
            this.dtypes = options.dtypes;
        }
    }

    get shape() {
        return [this._data.length, this.columns.length];
    }

    get size() {
        return this._data.length;
    }

    get data(){
        return this._data;
    }

    /**
     * 返回 Series 和其他元素的加法(二元运算符add)
     * @param other 
     * @param options 
     * @returns 
     */
    add(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val + other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回 Series 和其他元素的减法(二元运算符sub)
     * @param other 
     * @param options 
     * @returns 
     */
    sub(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val - other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回 Series 和其他元素的乘法运算(二元运算符mul)
     * @param other 
     * @param options 
     * @returns 
     */
    mul(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val * other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回 Series 和其他元素的浮点除法(二元运算符truediv)
     * @param other 
     * @param options 
     * @returns 
     */
    div(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val / other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回 Series 和其他元素的模(二元运算符mod)
     * @param other 
     * @param options 
     * @returns 
     */
    mod(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val % other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回级数和其他元素的指数幂(二元运算符pow)
     * @param other 
     * @param options 
     * @returns 
     */
    pow(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val ** other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 舍入 Series 中的浮点值
     * @param dp 
     * @param options 
     * @returns 
     */
    round(dp: number, options: any = {}) {
        const newData = this._data.map((val) => Number(val.toFixed(dp)));
        return new Series(newData, { index: this._index });
    }

    /**
     * 检查 Series 中的所有值是否都小于某个值
     * @param other 
     * @param options 
     * @returns 
     */
    lt(other: any, options: any = {}) {
        return this._data.every((val) => val < other);
    }

    /**
     * 返回 Series 和其他元素的大于(二元运算符gt)
     * @param other 
     * @param options 
     * @returns 
     */
    gt(other: Series, options: any = {}) {
        const newData = this.data.map((val, i) => val > other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 按元素返回小于或等于of的 Series 和other(二元运算符le)
     * @param other 
     * @param options 
     * @returns 
     */
    le(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val <= other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 检查 Series 中的所有值是否都大于或等于某个值
     * @param other 
     * @param options 
     * @returns 
     */
    ge(other: any, options: any = {}) {
        return this._data.every((val) => val >= other);
    }

    /**
     * 返回不等于系列和其他元素的值(二元运算符ne)
     * @param other 
     * @param options 
     * @returns 
     */
    ne(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val !== other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回等于系列和其他元素的值(二元运算符eq)
     * @param other 
     * @param options 
     * @returns 
     */
    eq(other: Series, options: any = {}) {
        const newData = this._data.map((val, i) => val === other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 对Series中的每个值调用函数
     * @param callable 
     * @param options 
     * @returns 
     */
    apply(callable: Function, options: any = {}) {
        const newData = this._data.map((val) => callable(val));
        return new Series(newData, { index: this._index });
    }

    /**
     * 将Series的值映射到函数或对象
     * @param callable 
     * @returns 
     */
    map(callable: Function) {
        const newData = this._data.map((val) => callable(val));
        return new Series(newData, { index: this._index });
    }


    /**
     * 返回删除了缺失值的新Series
     * @param options 
     * @returns 
     */
    dropNa(options: any = { inplace: false }) {
        const newData = this._data.filter((val) => !isNaN(val));
        if (options.inplace) {
            this._data = newData;
            return this;
        }
        return new Series(newData, { index: this._index });
    }

    /**
     * 使用指定的方法填充NaN值
     * @param options 
     * @returns 
     */
    fillNa(options: any = { inplace: false }) {
        const newData = this._data.map((val) => (isNaN(val) ? options.value : val));
        if (options.inplace) {
            this._data = newData;
            return this;
        }
        return new Series(newData, { index: this._index });
    }

    /**
     * 检测缺失值
     * @returns 
     */
    isNa(): boolean {
        return this._data.some((val) => isNaN(val));
    }

    /**
     * 替换值
     * @param oldValue 
     * @param newValue 
     * @param options 
     * @returns 
     */
    replace(oldValue: any, newValue: any, options: any = { inplace: false }) {
        const newData = this._data.map((val) => (val === oldValue ? newValue : val));
        if (options.inplace) {
            this._data = newData;
            return this;
        }
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回Series和其他Series之间的逻辑或
     * @param other 
     * @returns 
     */
    or(other: Series) {
        const newData = this._data.map((val, i) => val || other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回Series和其他Series之间的逻辑与
     * @param other 
     * @returns 
     */
    and(other: Series) {
        const newData = this._data.map((val, i) => val && other.data[i]);
        return new Series(newData, { index: this._index });
    }

    /**
     * 返回对Series值进行排序的整数索引
     * @param options 
     * @returns 
     */
    argSort(options: any = { ascending: true }) {
        const sortedIndex = this._index.slice().sort((a, b) => {
            if (options.ascending) {
                return this._data[a] - this._data[b];
            } else {
                return this._data[b] - this._data[a];
            }
        });
        return sortedIndex;
    }

    /**
     * 返回 Series 中最小值的位置
     * @returns 
     */
    argMin() {
        let minIndex = 0;
        for (let i = 1; i < this._data.length; i++) {
            if (this._data[i] < this._data[minIndex]) {
                minIndex = i;
            }
        }
        return minIndex;
    }

    /**
     * 返回 Series 中最大值的位置
     * @param options 
     * @returns 
     */
    argMax(options: any = { ascending: true, inplace: false }) {
        let maxIndex = 0;
        for (let i = 1; i < this._data.length; i++) {
            if (this._data[i] > this._data[maxIndex]) {
                maxIndex = i;
            }
        }
        return maxIndex;
    }

    /**
     * 按值排序
     * @param options 
     * @returns 
     */
    sortValues(options: any = {}) {
        const sortedData = this._data.slice().sort((a, b) => a - b);
        const sortedIndex = this._index.slice().sort((a, b) => {
            if (options.ascending) {
                return this._data[a] - this._data[b];
            } else {
                return this._data[b] - this._data[a];
            }
        });
        return new Series(sortedData, { index: sortedIndex });
    }



    /**
     * 将系列打印到控制台
     */
    print(...params:any[]) {
        // TODO: Print the Series to the console in a table format.
        // console.table(this._data);
        console.log(...params,this._data);
        
    }
}

export {
    Series
}